Trò chơi Pac-Man

20.587 lượt xem;
1 using UnityEngine;
2 using
System.Collections;
3 using
System.Collections.Generic;
4
5
6 public
class AI : MonoBehaviour {
7
8     
public Transform target;
9
10     
private List<TileManager.Tile> tiles = new List<TileManager.Tile>();
11     
private TileManager manager;
12     
public GhostMove ghost;
13
14     
public TileManager.Tile nextTile = null;
15     
public TileManager.Tile targetTile;
16     TileManager.Tile currentTile;
17
18     
void Awake()
19     {
20         manager = GameObject.Find(
"Game Manager").GetComponent<TileManager>();
21         tiles = manager.tiles;
22
23         
if(ghost == null) Debug.Log ("game object ghost not found");
24         
if(manager == null) Debug.Log ("game object Game Manager not found");
25     }
26
27     
public void AILogic()
28     {
29         
// get current tile
30         Vector3 currentPos =
new Vector3(transform.position.x + 0.499f, transform.position.y + 0.499f);
31         currentTile = tiles[manager.Index ((
int)currentPos.x, (int)currentPos.y)];
32         
33         targetTile = GetTargetTilePerGhost();
34         
35         
// get the next tile according to direction
36         
if(ghost.direction.x > 0) nextTile = tiles[manager.Index ((int)(currentPos.x+1), (int)currentPos.y)];
37         
if(ghost.direction.x < 0) nextTile = tiles[manager.Index ((int)(currentPos.x-1), (int)currentPos.y)];
38         
if(ghost.direction.y > 0) nextTile = tiles[manager.Index ((int)currentPos.x, (int)(currentPos.y+1))];
39         
if(ghost.direction.y < 0) nextTile = tiles[manager.Index ((int)currentPos.x, (int)(currentPos.y-1))];
40         
41         
if(nextTile.occupied || currentTile.isIntersection)
42         {
43             
//---------------------
44             
// IF WE BUMP INTO WALL
45             
if(nextTile.occupied && !currentTile.isIntersection)
46             {
47                 
// if ghost moves to right or left and there is wall next tile
48                 
if(ghost.direction.x != 0)
49                 {
50                     
if(currentTile.down == null) ghost.direction = Vector3.up;
51                     
else ghost.direction = Vector3.down;
52                     
53                 }
54                 
55                 
// if ghost moves to up or down and there is wall next tile
56                 
else if(ghost.direction.y != 0)
57                 {
58                     
if(currentTile.left == null) ghost.direction = Vector3.right;
59                     
else ghost.direction = Vector3.left;
60                     
61                 }
62                 
63             }
64             
65             
//---------------------------------------------------------------------------------------
66             
// IF WE ARE AT INTERSECTION
67             
// calculate the distance to target from each available tile and choose the shortest one
68             
if(currentTile.isIntersection)
69             {
70                 
71                 
float dist1, dist2, dist3, dist4;
72                 dist1 = dist2 = dist3 = dist4 =
999999f;
73                 
if(currentTile.up != null && !currentTile.up.occupied && !(ghost.direction.y < 0)) dist1 = manager.distance(currentTile.up, targetTile);
74                 
if(currentTile.down != null && !currentTile.down.occupied && !(ghost.direction.y > 0)) dist2 = manager.distance(currentTile.down, targetTile);
75                 
if(currentTile.left != null && !currentTile.left.occupied && !(ghost.direction.x > 0)) dist3 = manager.distance(currentTile.left, targetTile);
76                 
if(currentTile.right != null && !currentTile.right.occupied && !(ghost.direction.x < 0)) dist4 = manager.distance(currentTile.right, targetTile);
77                 
78                 
float min = Mathf.Min(dist1, dist2, dist3, dist4);
79                 
if(min == dist1) ghost.direction = Vector3.up;
80                 
if(min == dist2) ghost.direction = Vector3.down;
81                 
if(min == dist3) ghost.direction = Vector3.left;
82                 
if(min == dist4) ghost.direction = Vector3.right;
83                 
84             }
85             
86         }
87         
88         
// if there is no decision to be made, designate next waypoint for the ghost
89         
else
90         {
91             ghost.direction = ghost.direction;
// setter updates the waypoint
92         }
93     }
94
95     
public void RunLogic()
96     {
97         
// get current tile
98         Vector3 currentPos =
new Vector3(transform.position.x + 0.499f, transform.position.y + 0.499f);
99         currentTile = tiles[manager.Index ((
int)currentPos.x, (int)currentPos.y)];
100
101         
// get the next tile according to direction
102         
if(ghost.direction.x > 0) nextTile = tiles[manager.Index ((int)(currentPos.x+1), (int)currentPos.y)];
103         
if(ghost.direction.x < 0) nextTile = tiles[manager.Index ((int)(currentPos.x-1), (int)currentPos.y)];
104         
if(ghost.direction.y > 0) nextTile = tiles[manager.Index ((int)currentPos.x, (int)(currentPos.y+1))];
105         
if(ghost.direction.y < 0) nextTile = tiles[manager.Index ((int)currentPos.x, (int)(currentPos.y-1))];
106
107         
//Debug.Log (ghost.direction.x + " " + ghost.direction.y);
108         
//Debug.Log (ghost.name + ": Next Tile (" + nextTile.x + ", " + nextTile.y + ")" );
109
110         
if(nextTile.occupied || currentTile.isIntersection)
111         {
112             
//---------------------
113             
// IF WE BUMP INTO WALL
114             
if(nextTile.occupied && !currentTile.isIntersection)
115             {
116                 
// if ghost moves to right or left and there is wall next tile
117                 
if(ghost.direction.x != 0)
118                 {
119                     
if(currentTile.down == null) ghost.direction = Vector3.up;
120                     
else ghost.direction = Vector3.down;
121                     
122                 }
123                 
124                 
// if ghost moves to up or down and there is wall next tile
125                 
else if(ghost.direction.y != 0)
126                 {
127                     
if(currentTile.left == null) ghost.direction = Vector3.right;
128                     
else ghost.direction = Vector3.left;
129                     
130                 }
131                 
132             }
133             
134             
//---------------------------------------------------------------------------------------
135             
// IF WE ARE AT INTERSECTION
136             
// choose one available option at random
137             
if(currentTile.isIntersection)
138             {
139                 List<TileManager.Tile> availableTiles =
new List<TileManager.Tile>();
140                 TileManager.Tile chosenTile;
141                 
if(currentTile.up != null && !currentTile.up.occupied && !(ghost.direction.y < 0)) availableTiles.Add (currentTile.up);
142                 
if(currentTile.down != null && !currentTile.down.occupied && !(ghost.direction.y > 0)) availableTiles.Add (currentTile.down);
143                 
if(currentTile.left != null && !currentTile.left.occupied && !(ghost.direction.x > 0)) availableTiles.Add (currentTile.left);
144                 
if(currentTile.right != null && !currentTile.right.occupied && !(ghost.direction.x < 0)) availableTiles.Add (currentTile.right);
145
146                 
int rand = Random.Range(0, availableTiles.Count);
147                 chosenTile = availableTiles[rand];
148                 ghost.direction = Vector3.Normalize(
new Vector3(chosenTile.x - currentTile.x, chosenTile.y - currentTile.y, 0));
149                 
//Debug.Log (ghost.name + ": Chosen Tile (" + chosenTile.x + ", " + chosenTile.y + ")" );
150             }
151             
152         }
153         
154         
// if there is no decision to be made, designate next waypoint for the ghost
155         
else
156         {
157             ghost.direction = ghost.direction;
// setter updates the waypoint
158         }
159     }
160
161
162     TileManager.Tile GetTargetTilePerGhost()
163     {
164         Vector3 targetPos;
165         TileManager.Tile targetTile;
166         Vector3 dir;
167
168         
// get the target tile position (round it down to int so we can reach with Index() function)
169         
switch(name)
170         {
171         
case "blinky": // target = pacman
172             targetPos =
new Vector3 (target.position.x+0.499f, target.position.y+0.499f);
173             targetTile = tiles[manager.Index((
int)targetPos.x, (int)targetPos.y)];
174             
break;
175         
case "pinky": // target = pacman + 4*pacman's direction (4 steps ahead of pacman)
176             dir = target.GetComponent<PlayerController>().getDir();
177             targetPos =
new Vector3 (target.position.x+0.499f, target.position.y+0.499f) + 4*dir;
178
179             
// if pacmans going up, not 4 ahead but 4 up and 4 left is the target
180             
// read about it here: http://gameinternals.com/post/2072558330/understanding-pac-man-ghost-behavior
181             
// so subtract 4 from X coord from target position
182             
if(dir == Vector3.up) targetPos -= new Vector3(4, 0, 0);
183
184             targetTile = tiles[manager.Index((
int)targetPos.x, (int)targetPos.y)];
185             
break;
186         
case "inky": // target = ambushVector(pacman+2 - blinky) added to pacman+2
187             dir = target.GetComponent<PlayerController>().getDir();
188             Vector3 blinkyPos = GameObject.Find (
"blinky").transform.position;
189             Vector3 ambushVector = target.position +
2*dir - blinkyPos ;
190             targetPos =
new Vector3 (target.position.x+0.499f, target.position.y+0.499f) + 2*dir + ambushVector;
191             targetTile = tiles[manager.Index((
int)targetPos.x, (int)targetPos.y)];
192             
break;
193         
case "clyde":
194             targetPos =
new Vector3 (target.position.x+0.499f, target.position.y+0.499f);
195             targetTile = tiles[manager.Index((
int)targetPos.x, (int)targetPos.y)];
196             
if(manager.distance(targetTile, currentTile) < 9)
197                 targetTile = tiles[manager.Index (
0, 2)];
198             
break;
199         
default:
200             targetTile =
null;
201             Debug.Log (
"TARGET TILE NOT ASSIGNED");
202             
break;
203         
204         }
205         
return targetTile;
206     }
207 }


get current tile

get the next tile according to direction

---------------------

IF WE BUMP INTO WALL

if ghost moves to right or left and there is wall next tile

if ghost moves to up or down and there is wall next tile

---------------------------------------------------------------------------------------

IF WE ARE AT INTERSECTION

calculate the distance to target from each available tile and choose the shortest one

if there is no decision to be made, designate next waypoint for the ghost

ghost.direction = ghost.direction; setter updates the waypoint

get current tile

get the next tile according to direction

Debug.Log (ghost.direction.x + " " + ghost.direction.y);

Debug.Log (ghost.name + ": Next Tile (" + nextTile.x + ", " + nextTile.y + ")" );

---------------------

IF WE BUMP INTO WALL

if ghost moves to right or left and there is wall next tile

if ghost moves to up or down and there is wall next tile

---------------------------------------------------------------------------------------

IF WE ARE AT INTERSECTION

choose one available option at random

Debug.Log (ghost.name + ": Chosen Tile (" + chosenTile.x + ", " + chosenTile.y + ")" );

if there is no decision to be made, designate next waypoint for the ghost

ghost.direction = ghost.direction; setter updates the waypoint

get the target tile position (round it down to int so we can reach with Index() function)

case "blinky": target = pacman

case "pinky": target = pacman + 4*pacman's direction (4 steps ahead of pacman)

if pacmans going up, not 4 ahead but 4 up and 4 left is the target

read about it here: http:gameinternals.compost2072558330understanding-pac-man-ghost-behavior

so subtract 4 from X coord from target position

case "inky": target = ambushVector(pacman+2 - blinky) added to pacman+2



Gõ tìm kiếm nhanh...